1

其实用这个组件之前,原先是想接着用webuploader的,毕竟用过了,比较熟悉,而且也很好用。然鹅,因为是要上传到七牛,遇到了跨域的问题,尝试过网上的几种解决方法,都没用。只好用七牛文档里面的plupload,hhhhhh,官方文档推荐的,总归不会有什么问题~其实这篇文章咧,不是纯粹的怎么用plupload,会有一部分逻辑处理(脑子实在不好用,怕忘记了到时候还要重新想一遍逻辑,想想还是记下来吧)

https://developer.qiniu.com/k... 这个是七牛官网Javascript SDK的文档,项目过程中遇到的问题,也都是直接翻文档。因为用的plupload,有些参数七牛的文档没那么详细,http://www.cnblogs.com/2050/p... 这个链接是从七牛官网跳转过去的~很详细。由于官方文档已经写得很详细,这边就不过多的介绍参数、方法啥的,把项目中有注意到的参数、遇到的问题及解决方法整理一下。

大致过程是这样的

  1. 可以去github上面下载SDK源码,也可以通过NPM或者Bower安装。(官网有安装教程)

  2. 把js文件引入,我是用plupload.full.min.js、moxie.min.js、qiniu.min.js、Moxie.swf

  3. 因为是前端的关系,七牛的账号密码,包括token、下载资源用的bucket域名等这些是后台的小伙伴提供的,在用到图片上传之前,先通过后台小伙伴提供的接口请求七牛的token

  4. 接下去就可以写代码啦(贴完代码发现自己写了好一些逻辑处理,赶紧跳上来先把一些可以分享的东西写到上面来)

auto_start:是否自动上传,一般单图片上传的话,我会设会true,并且在FileUploaded事件中获取到图片的地址后,在页面中显示预览。多图片的话,就设为false,等到提交时,调用start方法一起上传,比如imgUploader.start(),上传的时间会久一点,但是不会有很多无用的图片占用存储空间(这也是项目中的需求啦)

在项目中,有多个地方用到单图片上传,我就把上传封装在一个方法中,这样可能会想要重写某个事件,可以通过绑定该事件实现,比如imgUploader.bind('FileUploaded', function (up, file, info) {));

在多图片上传的过程中,经常会出现http error.的错误,但是单图片从来不会。一开始以为是一下子上传太多张的缘故,就把auto_start改为true,然鹅还是会报错。。。
我抱着天无绝人之路盯着chrome开发者工具中的network看了好久,发现报http error的IP都是同一个!!!我就打开qiniu.js拿了上传域名中的http://up.qiniu.com去解析,发现真有那个IP,再然后,我把http://up-z2.qiniu.com全部换成http://upload-z2.qiniu.com,就可以了~由于不知道为什么会这样,所以只能说如果有遇到跟我一样的问题可以试试看,不保证有用~hhhhh

还有一个问题昂,顺便提一下,项目中,我有使用requirejs,因为plupload和qiniu.js这些不是按AMD或者CMD啥的规范组织的,做了一下处理,大约长这样

shim: {
    'moxie': {
        deps: ['jquery']
    },
    'plupload': {
        exports: 'plupload'
    },
    'Qiniu': {
        deps: ['plupload'],
        exports: 'Qiniu'
    }
}

单图片上传没啥好说的,直接上多图片上传的代码

// 界面的上传按钮和图片列表
<div id="uploader">
    <div id="uploaderShopContainer">
    <!--用来存放item-->
    <div id="fileList" class="uploader-list"></div>
    <a class="btn-normal blue-btn" id="uploadShopPic" href="#" >
        <span>上传图片</span>
    </a>
    </div>
</div>
<ul id="shopPicList" class="pic-cont"></ul>
// js
var imgUploader, // 上传对象
    uploadStoreImgUrl = [], // 当前图片列表(在编辑的情况下,图片列表可能不会为空,这个变量也是作为表单上传中图片列表的参数)
    uploadSuccessList = [],  // 图片上传成功后返回的列表
    fileNameList = []; // 添加图片后的队列
$.ajax({
    url: 'api/qiniu/token', // 获取七牛token的url(这个是后台给的)
    method: 'GET',
    success: function (data) {
        imgUploader = Qiniu.uploader({
            runtimes: 'html5,flash,html4', // 上传模式,依次退化
            browse_button: 'uploadShopPic', // 上传选择的点选按钮,必需
            container: 'uploaderShopContainer', // 上传区域DOM ID,默认是browser_button的父元素
            flash_swf_url: '../vendor/js/plupload/Moxie.swf',
            dragdrop: false,
            auto_start: false, // 选择文件后自动上传,若关闭需要自己绑定事件触发上传
            multi_selection: true,
            unique_names: true,
            max_retries: 0,  // 上传失败最大重试次数
            save_key: false,
            uptoken:data.token, // 这个就是请求返回的七牛token啦
            uptoken_url:'api/qiniu/token',
            domain: '<Your bucket domain>', // bucket域名,下载资源时用到,必需
            chunk_size: '4mb',                  // 分块上传时,每块的体积
            resize:true,
            filters : { // 限制上传的文件类型、大小等
                mime_types: [{title : "Image files", extensions:"jpg,gif,png"}]
                },
           init: {
               'FilesAdded': function(up, files) {
               // 因为需求中这个图片列表最多只能有10张,判断是否超过,超过的则移除
                var count = files.length + uploadStoreImgUrl.length + fileNameList.length;
                if (files.length > 10 && (uploadStoreImgUrl.length+fileNameList.length) == 0) {
                    var addLength = files.length;
                    for (var i = addLength - 1; i > addLength-1; i--) {
                        imgUploader.removeFile(files[i].id);
                        files.splice(i, 1);
                    }
                }
                if (count > 10) {
                    var addFile = files.length - (count - 10) - 1, tempLength = files.length;
                    for (var m = tempLength-1; m > addFile; m--) {
                        imgUploader.removeFile(files[m].id);
                        files.splice(m, 1);
                    }
                }
                plupload.each(files, function(file) {

                    // 文件添加进队列后,处理相关的事情
                    // 上传前预览
                    var isAdd = true;
                    // 先判断要上传的图片是否重复
                    for (var i = 0; i < fileNameList.length; i++) {
                        if (file.name == fileNameList[i]) {
                            isAdd = false;
                            return false;
                        }
                    }
                    // 如果不是重复的,则添加到上传队列,并且在页面预览
                    if (isAdd) {
                        fileNameList.push(file.name);
                        var preloader = new mOxie.Image();
                        preloader.onload = function() {
                        preloader.downsize( 100, 100);
                        var imgItem = '<img id="'+file.id+'" name="'+file.name+'" src="'+preloader.getAsDataURL()+'" class="pic-thumbnail">';
                        var liCont = '<li style="margin-left: 8px;">'+imgItem+'<div class="icon-close close-icon"></div></li>';
                        $('#shopPicList').append(liCont);
                    };
                    preloader.load(file.getSource());
                }
            });

        },
        'BeforeUpload': function(up, file) {
            // 每个文件上传前,处理相关的事情
        },
        'UploadProgress': function(up, file) {
            // 每个文件上传时,处理相关的事情
         },
        'FileUploaded': function(up, file, info) {
            // 上传成功后,返回图片路径,domain就是上面的domain参
             var domain = up.getOption('domain');
             var res = '';
             if (typeof(info) == "string") {
                 res = $.parseJSON(info);
             } else {
                 res = info.response;
                 if (typeof(res) == "string") {
                     res = $.parseJSON(res);
                 }
             }
             uploadStoreImgUrl.push(domain + res.key);
             uploadSuccessList.push(res.key);
        },
        'Error': function(up, file, err, errTip) {
            base.hideLoading();
            //上传出错时,处理相关的事情
            if (file.code=='-600'){
                base.showAlertDialog('上传图片的大小不能超过10mb!');
            } else if (file.code=='-601'){
                base.showAlertDialog('上传图片的格式有误!')
            } else {
                base.showAlertDialog(err);
            }
        },
        'UploadComplete': function(files) {
            //队列文件处理完毕后,处理相关的事情
            // 如果上传成功返回的图片个数和队列中的图片个数一样,则所有图片上传成功
            if (uploadSuccessList.length == fileNameList.length) {
                
            }

        },
        'Key': function(up, file) {
            // 若想在前端对每个文件的key进行个性化处理,可以配置该函数
            // 该配置必须要在 unique_names: false , save_key: false 时才生效
            var timestamp = Date.parse(new Date());
            var key = "data/car/web/uuid/"+file.name+'/'+timestamp;
            // do something with key
            return key;
        }
    }
});}});
        // 这个是删除的逻辑判断
        $('body').on('click', '.close-icon', function () {
            var id = $(this).siblings('.pic-thumbnail').attr('id');
            var name = $(this).siblings('.pic-thumbnail').attr('name');
            var liIndex = $(this).parent().index();
            // var uploadImgList = uploadStoreImgUrl.split(',');
            // uploadStoreImgUrl = '';
            if (liIndex < uploadStoreImgUrl.length) {
                uploadStoreImgUrl.splice(liIndex,1);
            }
            
            $(this).parent().remove();
            if (!(id == undefined || id == 'undefined')) {
                storeImgObj.removeFile(id);
                $.each(fileNameList, function(index,item){
                    // index是索引值(即下标)   item是每次遍历得到的值;
                    if(item == name){
                        fileNameList.splice(index,1);
                    }
                });
            }
        });

以上代码有很多逻辑处理,可以忽略。关键步骤都有添加注释,大致流程就是,
在图片添加到上传队列之前,先判断加了这些图片是否超过了图片的限制数量(比如10张),如果超过,则移除多余的(预览图片上面有删除按钮,可以删掉,再添加寄几想要的图片),如果图片有重复的,重复的也不添加,做完这些处理后,将图片添加到上传队列中。
等表单提交时,触发图片上传,把上传成功后返回的图片路径添加到图片成功列表和作为表单图片列表参数的列表,如果图片成功列表和图片队列中的图片数量一致,则提交表单。
删除的话,作为表单参数的列表中的图片地址和队列中的图片地址也要删除。

好吧。讲真,我太啰嗦了。。。= =


ermaoL
32 声望3 粉丝